﻿package server;

import info.*;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

import timetables.ExamTable;
import timetables.TimeDay;
import timetables.TimeSlot;
import timetables.TimeWeek;
import users.Prof;
import users.Student;
import users.TA;
import users.User;


public class AESSServer extends AbstractServer
{
	//Class variables *************************************************
	  
	/**
	 * The default port to listen on.
	 */
	final public static int DEFAULT_PORT = 5555;
	
	// 정규 시간표
	public static TimeWeek regularTable = new TimeWeek();
	
	// 시험 시간표
	public static ExamTable examTable = new ExamTable();
	
	// 강의실 정보
	public static LectureRoom[] lRoom = new LectureRoom[9];
	
	// 강좌 정보
	public static ArrayList<Course> course = new ArrayList<Course>();
	
	// 등록된 강의실 갯수
	private static int numberOfRoom = 0;
	  
	// 시험 시작 날짜(일단 1주일(5일) 기준으로 처리)
	private static int startDay;
	//Constructors ****************************************************
	  
	/**
	 * Constructs an instance of the echo server.
	 *
	 * @param port The port number to connect on.
	 */
	public AESSServer(int port) 
	{
		super(port);
	}

	  
	//Instance methods ************************************************
	  
	/**
	 * This method handles any messages received from the client.
	 *
	 * @param msg The message received from the client.
	 * @param client The connection from which the message originated.
	 */
	public void handleMessageFromClient(Object msg, ConnectionToClient client)
	{
		System.out.println("Message received: " + msg + " from " + client);
		System.out.println(client.getInfo("User"));
		String ret;
		
		if(msg == null)
			return;
		else if (msg instanceof String)			// String message일 경우
		{
			// 메시지를 구분
			String[] msgStr = msg.toString().split(":");
			
			try {
				if(msgStr[0].equals("#login"))		// 로그인인 경우
				{
					ret =  processLogin(msgStr[1]);
					if(!ret.equals("false")) 		// 로그인 성공 시
					{
						String type = ret.split(":")[1];
						readPersonalInfo(ret, client);
						System.out.println("login_success :" + type + ":" + client.getInfo("User"));
//						client.sendToClient((Object)("#login_success:"+type+":"+client.getInfo("User")));	// Ŭ���̾�Ʈ���� �α��� ���� �޽��� ���

						// 클라이언트에게 메시지 전송
						Message newMsg = new Message();
						newMsg.msgHeader = "#login_success:"+type;
						newMsg.msgBody = client.getInfo("User");
						client.sendToClient(newMsg);	
					}
					else		// 로그인 실패 시
					{
						System.out.println("login error");
						client.sendToClient("#login_failed");	// 로그인 실패 메시지를 전송
					}
				} 
				////////////////////////////// 관리자 전용
				else if (msgStr[0].equals("#readroom"))			// send information of lecture room
				{
					client.sendToClient(lRoom);
				}
/*				else if (msgStr[0].equals("#addcourse"))		// 강좌 목록 입력(관리자가 실행)
				{
					addCourse(msgStr[1]);
					// add information to file
					BufferedWriter bw = new BufferedWriter(new FileWriter("./bin/server/courselist.txt", true));
					
					bw.write(msgStr[1]);
					bw.newLine();
					// closing file
					bw.close();
				}*/
				else if (msgStr[0].equals("#initnumofRoom"))	// 강의실 정보 초기화
				{
					numberOfRoom = 0;
					
					File f = new File("./bin/server/roomlist.txt");
					System.out.println(f.delete());
				}
				else if (msgStr[0].equals("#adddate"))				// 시작일자 설정(직원)
				{
					startDay = Integer.parseInt(msgStr[1]);
				}
				//////////////////////// 교수 전용
				else if (msgStr[0].equals("#classcheck"))			// 시험기간 수업 여부 체크(교수용)
				{
					Prof usrInfo = (Prof) client.getInfo("User");
					
					if(msgStr[1].equals("not"))			// 수업을 안 할 경우						
					{
						// 강의목록에서 그 수업 찾아서 false로 기록
						int num = course.indexOf(usrInfo.getCourse().getID());
						course.get(num).setClass(false);
						
						// 교수 정보에도 수업 안 함 기록
						usrInfo.getCourse().setClass(false);
					}		
				}
				
				// request T num
				else if(msgStr[0].equals("#requestTnum")){
					String cCode = msgStr[1];
					
					for(int i=0;i<course.size();i++){
						if(course.get(i).getID().equals(cCode)){
							System.out.println("find " + cCode);
							
							
							Message newMsg = new Message();
							newMsg.msgHeader = "#totalStuNum:" + course.get(i).getNum_Students();
//							newMsg.msgBody = course.get(i).getNum_Students();
							client.sendToClient(newMsg);
						}
					}
				}
				
				// request check all stu
				else if(msgStr[0].equals("#requestCnum")){
					String cCode = msgStr[1];
					
					for(int i=0;i<course.size();i++){
						if(course.get(i).getID().equals(cCode)){
							System.out.println("find " + cCode);
							
							
							Message newMsg = new Message();
							newMsg.msgHeader = "#checkStuNum:" + course.get(i).getComplete();
//							newMsg.msgBody = course.get(i).getComplete();
							client.sendToClient(newMsg);
						}
					}

					
				}
				else if(msgStr[0].equals("#checkComplete")){
					String cCode = msgStr[1];
					for(int i=0;i<course.size();i++){
						if(cCode.equals(course.get(i).getID())){
							if(course.get(i).getComplete()){
								Message newMsg = new Message();
								newMsg.msgHeader = "#completeCourse";
								newMsg.msgBody = cCode;
								client.sendToClient(msgStr);
							}
						}
					}
				}
				
				else if (msgStr[0].equals("#deleteTA"))	{}			// TA 삭제
				else if (msgStr[0].equals("#registTA"))	{}			// TA 등록
				else if (msgStr[0].equals("#inquiryTA")) {}				// TA 조회
				else if (msgStr[0].equals("#gettotalcount"))			// 전체 수강 인원 조회
				{
					Course proCourse = ((Prof) client.getInfo("User")).getCourse();
					
					// 전체 수강 인원을 클라이언트에게 보냄
					client.sendToClient("#totalcount:"+proCourse.getNum_Students());
				}
				else if (msgStr[0].equals("#getinsertedcount"))			// 입력 인원 조회
				{
					Course proCourse = ((Prof) client.getInfo("User")).getCourse();
					
					// 파일을 읽어서 줄 수를 카운트한다.
					BufferedReader br = new BufferedReader(new FileReader(proCourse.getID()+".txt"));
					String strLine;
					int count = 0;
					while ((strLine = br.readLine()) != null)   {
					  count++;
					}
					
					br.close();
					// 입력한 수강 인원을 클라이언트에게 보냄
					client.sendToClient("#insetedcount:"+count);
				}
				/////////////////////// 학생 전용
				else if (msgStr[0].equals("#requireStartTest"))				// 시작하는 날짜 보내기(학생)
				{
					Message msg1 = new Message();
					msg1.msgHeader = "#startday:"+startDay;
//							// 클라이언트에게 보냄
					client.sendToClient(msg1);
					//client.sendToClient("#startday"+":"+startDay);	
				}
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
		else if (msg instanceof Message)		// 객체가 포함된 메시지인 경우
		{
			if(((Message) msg).msgHeader.equals("#addroom"))		// 강의실 추가의 경우
			{
				lRoom[numberOfRoom] = (LectureRoom) ((Message) msg).msgBody;
				
				
				// 파일에도 추가
				BufferedWriter bw;
				
				try {
					bw = new BufferedWriter(new FileWriter("./bin/server/roomlist.txt", true));
					bw.write(lRoom[numberOfRoom++].toString());
					bw.newLine();
					// closing file
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			else if (((Message) msg).msgHeader.equals("#addcourse"))	// 강좌 추가
			{
				System.out.println(((Message) msg).msgHeader);
				Course temp = (Course) ((Message)msg).msgBody;
				// 이건 강좌 목록에 추가
				course.add(temp);
				
				System.out.println(course.get(0).getName() + "," +course.get(0).getID());
				// 정규 시간표에 추가
				
			}
			else if (((Message) msg).msgHeader.equals("#addschedule"))	// 특별 일정 추가
			{
				SpecialSchedule temp = (SpecialSchedule) ((Message)msg).msgBody;
				examTable.setSpecialSchedule(temp);
		
			}
			
			// prefer exam time
			else if(((Message) msg).msgHeader.contains("#examTime")){
				String cCode = ((Message) msg).msgHeader.split(":")[1];
				
				System.out.println(cCode);
				
				String[] timeArr = new String[5];
				timeArr = (String[])((Message) msg).msgBody;
				
				for(int i=0;i<timeArr.length;i++){
					System.out.println(timeArr[i]);
				}
				
				int idx = 0;
				for(int i=0;i<course.size();i++){
					if(course.get(i).getID().equals(cCode)){
						idx = i;
						course.get(i).examTime = timeArr;
						System.out.println("find course");
					}
				}
				
				for(int i=0;i<5;i++){
					System.out.println(course.get(idx).examTime[i]);
				}
				
			}
			
			// #sendSchedule
			else if(((Message) msg).msgHeader.equals("#sendSchedule")){
				System.out.println(((Message) msg).msgHeader);
				Student std = (Student)((Message) msg).extraInfo;
				System.out.println("stu info : "+ std.id +"," + std.name);
				
				
				ArrayList<String>stuCourse = new ArrayList<String>();
				
				stuCourse = getCourseList(std.id);
				
				for(int i=0;i<stuCourse.size();i++){
					for(int j=0;j<=course.size();j++){
						
						System.out.println("i,j="+i+j);
						
						System.out.println(stuCourse.get(i));
						System.out.println(course.get(j).getID());
						
						// 학생이 등록한 과목들의 시험 스케쥴 정보 업데이트
						if(stuCourse.get(i).equals(course.get(j).getID())){
							boolean[][] sTable = (boolean[][]) ((Message) msg).msgBody;
							course.get(j).updateStudentTable(sTable);
						}
					}
				}
			}
			
			// 시험 선호 시간 받아오기
			else if(((Message) msg).msgHeader.contains("#examTime")){
				String cCode = ((Message) msg).msgHeader.split(":")[1];
				
				String[] time = (String[])((Message) msg).msgBody;
			}

		}
	}
	
	
	public ArrayList<String> getCourseList(String id){
		ArrayList<String>out = new ArrayList<String>();
		
		
		String temp = "";
		String pref = "";
		String surf = "";
		
		String pname =null;
		
		ArrayList<Course> mCourse = new ArrayList<Course>();
		
		File infile = new File(id+".txt");
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(infile));
		} catch (FileNotFoundException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		try {
			while( (temp = br.readLine()) != null ) {
				pref = temp.split(":")[0];
				surf = temp.split(":")[1];
				
				if(pref.equals("name")){
					pname = surf;
				} else if(pref.equals("id")){
					id = surf;
				} else if(pref.equals("course")){
					String[] courses = surf.split(",");
					for(int i=0;i<courses.length;i++){
						out.add(courses[i]);
					}
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		
		
		return out;
		
	}

	private static void addCourse(String string) {
		/*Course singleCourse;
		String[] arsSpl = string.split("=");
		
		// Course형 객체 생성(과목명, 과목코드, 시간, 담당교수, 학생수) 
		singleCourse = new Course(arsSpl[0], arsSpl[1], arsSpl[2], arsSpl[3], Integer.parseInt(arsSpl[4]));
		
		course.add(singleCourse);*/
	}

	// 로그인 진행
	public String processLogin(String ars){
		String[] arsSpl = ars.split("=");
		String fileLine;
		String result = "false";
		
		String id = arsSpl[0];
		String pass = arsSpl[1];
		
		/*
		 * 1. 파일을 열어 멤버 확인
		 * 2. 아이디, 비번, 권한 확인
		 * 3. 아이디, 비번 둘 다 맞으면 그 사람의 id를 반환
		 * 4. 하나라도 틀리면 false
		 */
		try
		{
			BufferedReader in = new BufferedReader(new FileReader("./bin/server/members.txt"));
			
			while ((fileLine = in.readLine()) != null)
			{
				// 파일 열면서 계속 추적
				if(fileLine.split("=")[0].equals(id) && fileLine.split("=")[1].equals(pass)) {
					String permission = fileLine.split("=")[2];
					// 결과값 만들기
					result = id + ":" + permission;
					break;
				}
				else {
					result = "false";
				}
			}
			
			// 파일 닫음
			in.close();
			
		}
		catch (FileNotFoundException ex)	// 파일 없으면?
		{
			ex.printStackTrace();
		}
		catch (IOException ioex)			// IOException 발생시
		{
			ioex.printStackTrace();
		}
		
		// 결과값 반환
		return result;
	}
	
	/**
	 * This method overrides the one in the superclass.  Called
	 * when the server starts listening for connections.
	 */
	protected void serverStarted()
	{
		System.out.println("Server listening for connections on port " + getPort());
	}
	  
	/**
	 * This method overrides the one in the superclass.  Called
	 * when the server stops listening for connections.
	 */
	protected void serverStopped()
	{
		
		System.out.println("Server has stopped listening for connections.");
	}
	  
	/**
	 * 강좌 목록 초기화
	 */
	public static void initCourse(){
		String fileLine;
		// 파일 열고
		try
		{
			BufferedReader in = new BufferedReader(new FileReader("./bin/server/courselist.txt"));
			
			while ((fileLine = in.readLine()) != null)
			{
				// 반복해서 강좌목록에 추가
				addCourse(fileLine);
			}
			
			// 파일 닫고 끝
			in.close();
			
		}
		catch (FileNotFoundException ex)	// 파일 없으면 걍 끝
		{ }
		catch (IOException ioex)			// IOException 발생시
		{
			ioex.printStackTrace();
		}
	}
	
	/**
	 * 강의실 목록 받아 오기
	 */
	public static void initLectureRoom(){
		String fileLine;
		int i = 0, j;
		// 파일 열고
		try
		{
			BufferedReader in = new BufferedReader(new FileReader("./bin/server/roomlist.txt"));
			
			while ((fileLine = in.readLine()) != null)
			{
				//강의실 객체 생성
				LectureRoom singleRoom = new LectureRoom(fileLine.split("=")[0], Integer.parseInt(fileLine.split("=")[2]), fileLine.split("=")[1]);
				lRoom[i] = singleRoom;
				numberOfRoom = i++;
			}
			
			// 그 다음부터는 null값 저장
			for(j = numberOfRoom+1 ; j < lRoom.length; j++)
			{
				lRoom[j] = null;
			}
			// 파일 닫고 끝
			in.close();
			
		}
		catch (FileNotFoundException ex)	// 파일 없으면 끝
		{ }
		catch (IOException ioex)			// IOException 발생시
		{
			ioex.printStackTrace();
		}
	}
	//Class methods ***************************************************
	  
	/**
	 * This method is responsible for the creation of 
	 * the server instance (there is no UI in this phase).
	 *
	 * @param args[0] The port number to listen on.  Defaults to 5555 
	 *          if no argument is entered.
	 */
	public static void main(String[] args) 
	{
		int port = 0; //Port to listen on
		
		
		// init server data (timetables, courses, lecturerooms...)
		// --------------------------------------------------------
		// initialize courses
		initCourse();
		
		// initialize lecture rooms 
		initLectureRoom();
		
	
		try
		{
			port = Integer.parseInt(args[0]); //Get port from command line
		}
		catch(Throwable t)
		{
			port = DEFAULT_PORT; //Set port to 5555
		}
			
		AESSServer sv = new AESSServer(port);
		    
		try 
		{
			sv.listen(); //Start listening for connections
		} 
		catch (Exception ex) 
		{
			System.out.println("ERROR - Could not listen for clients!");
		}
	}
	
	// 클라이언트가 서버에 연결하면 
	protected void clientConnected(ConnectionToClient client) 
	{
		System.out.println("Client has connected.");
	}
	
	// 클라이언트가 연결 끊으면
	synchronized protected void clientDisconnected(ConnectionToClient client)
	{
		System.out.println("Cliend has disconnected.");
		// 클라이언트의 정보를 파일로 저장
		User userInfo = (User) client.getInfo("User");
		
		if (userInfo != null)
		{
			try {
				BufferedWriter bw = new BufferedWriter(new FileWriter(userInfo.id+".txt"));
				
				bw.write("id:"+userInfo.id);
				bw.newLine();
				bw.write("name:"+userInfo.name);
				bw.newLine();
				if(userInfo instanceof Prof)				// 교수일 경우
					bw.write("course:"+((Prof)userInfo).getCourse().getID());
				else if (userInfo instanceof Student)		// 학생일 경우
				{
					bw.write("course:"+((Student)userInfo).getCourseList());
				}
				else if (userInfo instanceof TA)
				{
					bw.write("course:"+((TA)userInfo).getCourse());
					bw.write("cannottime:"+((TA)userInfo).getCannotTime());
				}
				bw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		else return;
	}
	
	/**
	 * find LectureRoom
	 * @param lrName : name of lectureRoom
	 * @return
	 */
	public LectureRoom findlRoom(String lrName){
		LectureRoom temp = null;
		
		for(int i=0;i<lRoom.length;i++){
			if(lRoom[i].getName().equals(lrName)){
				temp = lRoom[i];
				break;
			}
		}
		return temp;
	}
	
	/**
	 *  find Course(교수 이름을 기준으로 해서)
	 * @param cName : name of Course
	 * @return
	 */
	public Course findCourse(String cName){
		Course temp = null;
		
		for(int i=0;i<course.size();i++){
			if(course.get(i).getProfessor().equals(cName)){
				temp = course.get(i);
				return temp;
			}
		}
		
		return temp;
	}
	
	// read personal info. this method depends on client's permission
	public void readPersonalInfo (String ars, ConnectionToClient client) throws Exception{
		String id = ars.split(":")[0];
		String type = ars.split(":")[1];
		
		if(type.equals("1")){
//			readAdminInfo();
		} else if(type.equals("2")){
			readProfInfo(id, client);
		} else if(type.equals("4")){
			readStudentInfo(id,client);
		} else {
			readTAInfo(id, client);
		}
	}

	/**
	 * TA의 정보를 읽어옴
	 * @param id
	 * @param client
	 * @throws Exception 
	 */
	private void readTAInfo(String id, ConnectionToClient client) throws Exception {
		String temp = "";
		String pref = "";
		String surf = "";
		
		String pname =null,pcourse=null,cannotTime = null;
		
		File infile = new File(id+".txt");
		BufferedReader br = new BufferedReader(new FileReader(infile));
		while( (temp = br.readLine()) != null ) {
			pref = temp.split(":")[0];
			surf = temp.split(":")[1];
			
			if(pref.equals("name")){
				pname = surf;
			} else if(pref.equals("id")){
				id = surf;
			} else if(pref.equals("course")){
				pcourse = surf;
			} else if(pref.equals("cannotTime")) {
				cannotTime = surf;
			}
		}
		
		TA mTA = new TA();
		mTA.id = id;
		mTA.name = pname;
		mTA.setCannotTime(cannotTime);
		mTA.setCourse(pcourse);
		
		client.setInfo("User", mTA);
		br.close();
	}


	/**
	 *  Read professor's infomation
	 * @param pid
	 * @param client
	 * @throws IOException
	 */
	public void readProfInfo(String pid, ConnectionToClient client) throws IOException{
		String temp = "";
		String pref = "";
		String surf = "";
		
		String pname =null,pcourse=null;
		
		File infile = new File(pid+".txt");
		BufferedReader br = new BufferedReader(new FileReader(infile));
		while( (temp = br.readLine()) != null ) {
			pref = temp.split(":")[0];
			surf = temp.split(":")[1];
			
			if(pref.equals("name")){
				pname = surf;
			} else if(pref.equals("id")){
				pid = surf;
			} else if(pref.equals("course")){
				pcourse = surf;
			}
		}
		
		Prof mprof = new Prof();
		mprof.id = pid;
		mprof.name = pname;
		mprof.mCourse = findCourse(pcourse);
		mprof.course = pcourse;
		
		client.setInfo("User", mprof);
		br.close();
	}
	
	// read student's infomation
	public void readStudentInfo(String pid, ConnectionToClient client) throws IOException{
		
		System.out.println("read Stu info");
		String temp = "";
		String pref = "";
		String surf = "";
		
		String pname =null;
		
		ArrayList<Course> mCourse = new ArrayList<Course>();
		
		File infile = new File(pid+".txt");
		BufferedReader br = new BufferedReader(new FileReader(infile));
		while( (temp = br.readLine()) != null ) {
			pref = temp.split(":")[0];
			surf = temp.split(":")[1];
			
			if(pref.equals("name")){
				pname = surf;
			} else if(pref.equals("id")){
				pid = surf;
			} else if(pref.equals("course")){
				String[] courses = surf.split(",");
				for(int i=0;i<courses.length;i++){
					mCourse.add(findCourse(courses[i]));
				}
			}
		}
		
		Student stu = new Student();
		stu.id = pid;
		stu.name = pname;
		stu.mCourse = mCourse;
		client.setInfo("User", stu);
		
		System.out.println(client.getInfo("User"));
		
		br.close();
	}
	
	
}
